package com.file.word;


import cn.afterturn.easypoi.word.WordExportUtil;
import cn.afterturn.easypoi.word.entity.MyXWPFDocument;
import com.util.DateUtil;
import org.apache.poi.openxml4j.opc.OPCPackage;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * @author: cxt
 * @time: 2022/2/28
 */
public class ExportWordUtils {
    /**
     * 导出word
     * <p>第一步生成替换后的word文件，只支持docx</p>
     * <p>第二步下载生成的文件</p>
     * <p>第三步删除生成的临时文件</p>
     * 模版变量中变量格式：{{foo}}
     *
     * @param templatePath word模板地址
     * @param temDir       生成临时文件存放地址
     * @param fileName     文件名
     * @param params       替换的参数
     * @param request      HttpServletRequest
     * @param response     HttpServletResponse
     */
    public static void exportWord(String templatePath, String temDir, String fileName, Map<String, Object> params, HttpServletRequest request, HttpServletResponse response) throws UnsupportedEncodingException {
        if (templatePath.isEmpty()) {
            // 模板路径不能为空
        }

        if (temDir.isEmpty()) {
            // 临时文件路径不能为空
        }

        if (fileName.isEmpty()) {
            // 导出文件名不能为空
        }

        if (fileName.endsWith(".docx")) {
            // word导出请使用docx格式
        }

        if (!temDir.endsWith("/")) {
            temDir = temDir + File.separator;
        }

        File dir = new File(temDir);
        if (!dir.exists()) {
            dir.mkdirs();
        }

        try {
            String userAgent = request.getHeader("user-agent").toLowerCase();
            if (userAgent.contains("msie") || userAgent.contains("like gecko")) {
                fileName = URLEncoder.encode(fileName, "UTF-8");
            } else {
                fileName = new String(fileName.getBytes("utf-8"), "ISO-8859-1");
            }

            MyXWPFDocument doc = new MyXWPFDocument(OPCPackage.open(templatePath));

            WordExportUtil.exportWord07(doc, params);
            String tmpPath = temDir + fileName;
            FileOutputStream fos = new FileOutputStream(tmpPath);
            doc.write(fos);
            // 设置强制下载不打开
            response.setContentType("application/force-download");
            // 设置文件名
            response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);
            OutputStream out = response.getOutputStream();
            doc.write(out);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            delFileWord(temDir, fileName);//这一步看具体需求，要不要删
        }
    }

    /**
     * 删除零时生成的文件
     */
    public static void delFileWord(String filePath, String fileName) {
        File file = new File(filePath + fileName);
        File file1 = new File(filePath);
        boolean delete = file.delete();
        boolean delete1 = file1.delete();
    }

    /**
     * 批量下载文件
     *
     * @param ids      文件地址集合
     * @param response 返回
     */
    public void downloadCompressed(String ids, HttpServletResponse response) {
        // TODO 根据id去数据获取文件地址
        List<String> list = Arrays.asList(ids.split(","));

        ByteArrayOutputStream byteArrayOutputStream = null;
        OutputStream responseOutputStream = null;
        try {
            if (list.size() > 1) {
                byteArrayOutputStream = new ByteArrayOutputStream();
                ZipOutputStream zipOutputStream = new ZipOutputStream(byteArrayOutputStream);
                // 解决文件名重复报错
                ArrayList<String> repeatFileName = new ArrayList<>();
                // 遍历文件列表，将每个文件添加到压缩包中
                for (String entity : list) {
                    FileInputStream inputStream = new FileInputStream(entity);
                    ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
                    int red;
                    while ((red = inputStream.read()) != -1) {
                        byteArray.write(red);
                    }
                    byte[] aByte = byteArray.toByteArray();
                    // TODO 名称获取
                    Double v = Math.random() * 100;
                    String oldFileName = String.valueOf(v.intValue());
                    // 检查名称是否已经存在,为防止报错相同名称文件名称后面跟上数字
                    String finalOnlyFileName = oldFileName;
                    if (repeatFileName.contains(oldFileName)) {
                        long count = repeatFileName.stream().filter(str -> str.startsWith(oldFileName)).count();
                        String tempFileName = finalOnlyFileName.substring(0, finalOnlyFileName.lastIndexOf("."));
                        finalOnlyFileName = tempFileName + count + ".docx";
                    }
                    ZipEntry zipEntry = new ZipEntry(finalOnlyFileName);
                    repeatFileName.add(oldFileName); // 这里填写重复的名称onlyFileName，finalOnlyFileName 已经在if中被改变了；
                    zipOutputStream.putNextEntry(zipEntry);
                    zipOutputStream.write(aByte);
                }
                // 结束打包
                zipOutputStream.closeEntry();
                zipOutputStream.close();

                // 返回压缩包给前端
                response.setCharacterEncoding("UTF-8");
                response.setHeader("Content-Disposition", "attachment; filename=文档示例" + DateUtil.dateNowByStr("yyyyMMdd") + ".zip");
                response.setContentType("application/zip");
                byte[] bytes = byteArrayOutputStream.toByteArray();
                responseOutputStream = response.getOutputStream();
                responseOutputStream.write(bytes);
                responseOutputStream.flush();
            } else if (list.size() == 1) {
                // 只有一个文件时候返回文件，不返回压缩包
                FileInputStream inputStream = new FileInputStream(list.get(0));
                ByteArrayOutputStream byteArray = new ByteArrayOutputStream();
                int red;
                while ((red = inputStream.read()) != -1) {
                    byteArray.write(red);
                }
                byte[] aByte = byteArray.toByteArray();

                response.setCharacterEncoding("UTF-8");
                response.setHeader("Content-Disposition", "attachment; filename=文件名称");
//                String returnType = "docx".equals(uploaderVO.getFileExtension()) ? "application/vnd.openxmlformats-officedocument.wordprocessingml.document" : "application/msword";
//                response.setContentType("application/msword"); // doc文件返回
                response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document"); // doc文件返回
                responseOutputStream = response.getOutputStream();
                responseOutputStream.write(aByte);
                responseOutputStream.flush();
            } else {
                throw new RuntimeException("请求出错，未查询到数据");
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (!Objects.isNull(responseOutputStream)) {
                    responseOutputStream.close();
                }
                if (!Objects.isNull(byteArrayOutputStream)) {
                    byteArrayOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
